import os
import sys
import subprocess
import shlex
import shutil
import hashlib
import logging

from utils.file_type_detect import is_staticlib, is_sharedlib, is_objfile

def color_print(msg=""):
        
        print_msg = "\033[32m"
        print_msg += msg
        print_msg += "\033[0m"
        
        print(print_msg)


def real_binary_path(binary: str):
    
    if not isinstance(binary, str):
        return binary
    
    if os.path.isabs(binary):
        return binary
    
    dir_name = os.path.dirname(binary)
    if dir_name:
        return os.path.join(os.getcwd(), binary)
    else:
        return shutil.which(binary)
    
    
def real_file_path(file="", cwd=""):
    if not file:
        return file
    
    if not cwd:
        return os.path.realpath(file)

    if os.path.isabs(file):
        return file
    
    return os.path.join(cwd, file)


def run_command(command=[], env={}, cwd=""):
    
    if not env:
        env = dict(os.environ)
    
    if not cwd:
        cwd = os.getcwd()
    
    ret = subprocess.call(args=command, shell=False, env=env, cwd=cwd)
    
    return ret


def run_notty_command(command=[], env={}, cwd=""):
    
    if not env:
        env = dict(os.environ)
    
    if not cwd:
        cwd = os.getcwd()
        
    sp = subprocess.Popen(args=command, shell=False, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)

    sp.wait()
    
    std_out, std_err = sp.communicate()
    
    if std_out:
        std_out.decode()
        
    if sp.returncode:
        pass
    
    return sp.returncode, std_out, std_err

def run_reassemble_command(command=[], env={}):
    
    if not env:
        env = dict(os.environ)
    
    sp = subprocess.Popen(command, shell=False, env=env)
    
    std_out, std_err = sp.communicate()
    
    return sp.returncode
    
    
def active_capture_env(env={}, context=None):
    
    if not env:
        env = dict(os.environ)
    
    preload_path = context.CAPTURE_LIB
    
    env_key = "LD_PRELOAD"
    env_ori_value = env.get(env_key, "")
    
    if env_ori_value:
        preload_path = ':'.join([env_ori_value, preload_path])
    
    env[env_key] = preload_path
    logging.debug("active LD_PRELOAD LIB from %s" % preload_path)
    
def active_cache_env(env={}, context=None):
    if not context:
        return 
    if not env:
        env = dict(os.environ)
    
    preload_path = context.CACHE_LIB
    env_key = "LD_PRELOAD"
    env_ori_value = env.get(env_key, "")
    
    if env_ori_value:
        preload_path = ':'.join(env_ori_value, preload_path)
    
    env[env_key] = preload_path

def release_ld_env(env={}):
    
    if not env:
        env = dict(os.environ)

    if "LD_PRELOAD" in env:
        env.pop("LD_PRELOAD")

def is_sys_header(path=""):
    if not path:
        return True

    sys_path_prefixes = ["/usr/local/include", "/usr/include", "/usr/lib"]
    
    for prefix in sys_path_prefixes:
        if path.startswith(prefix):
            return True
    
    return False

def is_cpp_compiler(compiler=""):
    if "++" in compiler or "pp" in compiler:
        return True
    
    return False

def file_md5(file_path=""):
    
    if not os.path.exists(file_path) or not os.path.isfile(file_path):
        return ""
    
    m = hashlib.md5()
    with open(file_path, "rb") as f:
        while True:
            content = f.read(4096)
            if not content:
                break
            m.update(content)
        
    return m.hexdigest()

def str_md5(string=""):
    
    m = hashlib.md5()
    m.update(string.encode())
    
    return m.hexdigest()

def is_cpp_compiler(compiler=""):
    if not compiler:
        return False
    
    return '++' in compiler or 'pp' in compiler

def is_sys_file(path=""):
    sys_path = []
    if path in sys_path:
        return True
    return False

def get_binary_path(path=""):
    if not path:
        return
    
    bin_path = shutil.which(path)
    return bin_path

def remove_envs_by_keys(env={}, remove_list=[]):
    
    for key in remove_list:
        if env.get(key):
            env.pop(key)
            
def is_sys_lib(library=""):
    if not is_sharedlib(library) and not is_staticlib(library):
        return False
    
    sys_lib_dir = ["/usr/lib", "/usr/local/lib"]
    for dir in sys_lib_dir:
        if library.startswith(dir):
            return True
    
    return False

def is_sys_obj(file=""):
    file = os.path.abspath(file)
    if not is_objfile(file):
        return False

    sys_obj_dir = ["/usr/lib/x86_64-linux-gnu", "/usr/lib/gcc/x86_64-linux-gnu"]
    
    for dir in sys_obj_dir:
        if file.startswith(dir):
            return True
    
    return False